#include "graphics.h"
// #include <bits/stdc++.h>
#include <cstdio>
#include <cstdlib>
#include <conio.h>
#include <string>
#include <cstring>
#include <iostream>
#include <pthread.h>
#include "ocr.h"
#include "tiku.hpp"
#include "ScreenGrab.hpp"
using namespace std;
#define WIDTH 800
#define HEIGHT 600

pthread_mutex_t mutex;
Tiku tk("./tiku.db");
ScreenGrab sg;
string AppID = "119050963";
string API_Key = "vwSItpg3QXDY7Vg8fmSfTwWK";
string Secret_Key = "7J0v2bmaZzjJDwTzQPHpOaaCUO1osF9G";
map<string, string> options;
aip::Ocr ocr(AppID, API_Key, Secret_Key);


// char* quesion_c = nullptr;
// char* answer_c = nullptr;
string quesion;
string answer;

wchar_t* UTF8ToUnicode(const string& utf8str);
char* Unicode2TCHAR(wchar_t* unicodestr);
//将utf-8转换为GBK
char* UTF8ToGBK(const string& utf8str);

enum Page {MENU, SEARCH, SHOW, INSERT, HELP, EXIT};

int cur_page = MENU;

bool isSearched = false;

const char* start_menu[] = {
    "1.开始答题",
    "2.查看题库",
    "3.插入新题",
    "4.帮助",
    "5.退出"
};

class Button {
public:
    int _x, _y;
    int _w, _h;
    int _color = BLUE;
    string data;
public:
    Button(int x, int y, int w, int h, int color) 
    : _x{x}, _y{y}, _w{w}, _h{h}, _color{color} {
    }    
};

Button *menu_btn[5] = {0};

Button back_btn(0, 0, 40, 25, GREEN);
Button search_btn(350, 500, 100, 25, GREEN);


// g++ .\gui.o -L. -leasyx "-Wl,--defsym=__imp___iob_func=__imp___acrt_iob_func" -mconsole -o gui.exe

inline string read_text(Json::Value response) {
    string ret = "";
    for (auto words : response["words_result"]) {
        // cout << words["words"].asString();
        ret += words["words"].asString();
    }
    return ret;
}

void startMenu() {
    // outtextxy()
    for (int i = 0; i < 5; i++) {
        setfillcolor(menu_btn[i]->_color);
        bar(menu_btn[i]->_x, menu_btn[i]->_y, menu_btn[i]->_x + menu_btn[i]->_w, menu_btn[i]->_y + menu_btn[i]->_h);
        setcolor(BLACK);
        rectangle(menu_btn[i]->_x, menu_btn[i]->_y, menu_btn[i]->_x + menu_btn[i]->_w, menu_btn[i]->_y + menu_btn[i]->_h);
        setcolor(BLACK);
        setbkmode(TRANSPARENT);
        // wchar_t* unicodeText = UTF8ToUnicode(menu_btn[i]->data);
        // char* text = Unicode2TCHAR(unicodeText);
        char* text = UTF8ToGBK(menu_btn[i]->data);
        outtextxy(menu_btn[i]->_x + (menu_btn[i]->_w - (strlen(text) * 7)) / 2, menu_btn[i]->_y + (menu_btn[i]->_h - 15) / 2, text);
        delete [] text;
        // outtextxy(menu_btn[i]->_x + (menu_btn[i]->_w - (menu_btn[i]->data.length()) * 7) / 2, menu_btn[i]->_y + (menu_btn[i]->_h - 15) / 2, menu_btn[i]->data.c_str());
    }
}

void init() {
    back_btn.data = "返回";
    search_btn.data = "开始搜题";
    system("chcp 65001");
    pthread_mutex_init(&mutex, nullptr);
    // pthread_mutex_lock(&mutex);
    initgraph(WIDTH, HEIGHT, 0);
    int w = 100, h = 25;
    int x0 = (WIDTH - w) / 2;
    int y0 = (HEIGHT - (h * 4)) / 2;
    int off_y = 20;
    for (int i = 0; i < 5; i++) {
        menu_btn[i] = new Button(x0, y0 + i * (h + off_y), w, h, GREEN);
        menu_btn[i]->data = start_menu[i];
    }
    setbkcolor(WHITE);
    cleardevice();
    LOGFONT f;
    gettextstyle(&f);
    f.lfHeight = 15;
    f.lfWeight = 7;
    strcpy(f.lfFaceName, "Segoe UI Black");
    f.lfQuality = ANTIALIASED_QUALITY; //抗锯齿效果
    settextcolor(BLACK);
    settextstyle(&f);
}

void* btn_clicked(void* arg) {
    while (1) {
        ExMessage msg;
        if (peekmessage(&msg)) {
            // cout << "*****\n";
            if (msg.message != WM_LBUTTONDOWN) {
                continue;
            }
            cout << msg.x << ", " << msg.y << endl;
            if (msg.x > back_btn._x && 
                msg.x < back_btn._x + back_btn._w &&
                msg.y > back_btn._y && msg.y <back_btn._h + back_btn._y) {
                    cur_page = MENU;
                    cout << "返回" << "clicked!" << endl;
                    continue;
                }
            for (int i = 0; i < 5; i++) {
                if (cur_page != MENU) {
                    break;
                }
                if (msg.x > menu_btn[i]->_x && 
                    msg.x < menu_btn[i]->_x + menu_btn[i]->_w &&
                    msg.y > menu_btn[i]->_y && msg.y < menu_btn[i]->_h + menu_btn[i]->_y) {
                        if (cur_page == MENU) {
                            cur_page = i + 1;
                        }
                        cout << menu_btn[i]->data << "clicked!" << endl;
                        break;
                    }
            }
            if (cur_page == SEARCH) {
                try {
                    if (msg.x > search_btn._x && 
                        msg.x < search_btn._x + search_btn._w &&
                        msg.y > search_btn._y && msg.y <search_btn._h + search_btn._y) {
                            pthread_mutex_trylock(&mutex);
                            cout << "搜索" << "clicked!" << endl;
                            sg.screenCapture(L"1.bmp", 0, 118, 334, 103);
                            Json::Value response = ocr.general_basic("./1.bmp", options);
                            // cout << response << endl;
                            string q = read_text(response);
                            cout << q << endl;
                            cout << "question: " << q << endl;
                            search_result sr = tk.search(q);
                            cout << sr.q << " " << sr.a << " " << sr.similarity << endl;
                            quesion = "题目: ";
                            quesion += sr.q;
                            answer = "问题: ";
                            answer += sr.a;
                            pthread_mutex_unlock(&mutex);
                            isSearched = true;
                            continue;
                        }
                } catch(exception& e) {
                    cout << e.what() << endl;
                }
            }
        }
    }
    return nullptr;
}

wchar_t* UTF8ToUnicode(const string& utf8str) {
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), -1, nullptr, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_UTF8, 0, utf8str.c_str(), -1, buf, len);
    return buf;
}

char* Unicode2TCHAR(wchar_t* unicodestr) {
    int len = WideCharToMultiByte(CP_ACP, 0, unicodestr, -1, NULL, 0, NULL, NULL);
    char* multiByteText = new char[len];
    WideCharToMultiByte(CP_ACP, 0, unicodestr, -1, multiByteText, len, NULL, NULL);
    return multiByteText;
}

char* UTF8ToGBK(const string& utf8str) {
    wchar_t* unicodeText = UTF8ToUnicode(utf8str);
    char* text = Unicode2TCHAR(unicodeText);
    delete [] unicodeText;
    return text;
}

void searchUI() {
    setfillcolor(search_btn._color);
    bar(search_btn._x, search_btn._y, search_btn._x + search_btn._w, search_btn._y + search_btn._h);
    setcolor(BLACK);
    rectangle(search_btn._x, search_btn._y, search_btn._x + search_btn._w, search_btn._y + search_btn._h);
    setcolor(BLACK);
    setbkmode(TRANSPARENT);
    char* text = UTF8ToGBK(search_btn.data);
    outtextxy(search_btn._x + (search_btn._w - (strlen(text) * 7)) / 2, search_btn._y + (search_btn._h - 15) / 2, text);
    delete [] text;
    if (isSearched) {
        // cout << "answer_c = " << answer_c << endl;
        // pthread_mutex_lock(&mutex);
        pthread_mutex_trylock(&mutex);
        char* quesion_c = UTF8ToGBK(quesion);
        char* answer_c = UTF8ToGBK(answer);
        outtextxy(0 + (WIDTH - (strlen(quesion_c)) * 7) / 2, 40, quesion_c);
        outtextxy(0 + (WIDTH - (strlen(answer_c)) * 7) / 2, 80, answer_c);
        delete [] quesion_c;
        delete [] answer_c;
        pthread_mutex_unlock(&mutex);
    }
}

int main() {
    init();
    pthread_t tid;
    pthread_create(&tid, nullptr, btn_clicked, nullptr);
    tk.show();
    while (1) {
        BeginBatchDraw();
        setcolor(WHITE);
        cleardevice();
        setfillcolor(back_btn._color);
        bar(back_btn._x, back_btn._y, back_btn._x + back_btn._w, back_btn._y + back_btn._h);
        setcolor(BLACK);
        rectangle(back_btn._x, back_btn._y, back_btn._x + back_btn._w, back_btn._y + back_btn._h);
        setcolor(BLACK);
        setbkmode(TRANSPARENT);
        char* text = UTF8ToGBK(back_btn.data);
        outtextxy(back_btn._x + (back_btn._w - (strlen(text) * 7)) / 2, back_btn._y + (back_btn._h - 15) / 2, text);
        delete [] text;
        switch (cur_page) {
            case MENU:
            {
                startMenu();
                break;
            }
            case SEARCH:
            {
                searchUI();
                break;
            }
            case SHOW:
            {
                break;
            }
            case INSERT:
            {
                break;
            }
            case HELP:
            {
                break;
            }
            case EXIT:
            {
                exit(0);
                break;
            }
        }
        EndBatchDraw();
    }
    // getchar();
    closegraph();
}
